package com.whjk.system.biz.service.impl;

import cn.hutool.core.util.IdcardUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.google.gson.Gson;
import com.whjk.core.common.utils.NoUtils;
import com.whjk.core.common.utils.PinYinUtil;
import com.whjk.core.security.uitls.SecurityUtils;
import com.whjk.system.biz.mapper.WhjkPersonMapper;
import com.whjk.system.biz.service.*;
import com.whjk.system.data.dto.*;
import com.whjk.system.data.entity.*;
import com.whjk.system.data.po.WhjkPackageRelPo;
import com.whjk.system.data.uitls.ExcelImportUtils;
import com.whjk.system.data.vo.AmountVo;
import com.whjk.system.data.vo.InquiryTemplateVo;
import com.whjk.system.data.vo.ZhxmVo;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;
import org.springframework.util.CollectionUtils;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletResponse;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * <p>
 * 个人体检人员信息 服务实现类
 * </p>
 *
 * @author hl
 * @since 2023-06-28
 */
@Slf4j
@Service
public class WhjkPersonServiceImpl extends ServiceImpl<WhjkPersonMapper, WhjkPerson> implements WhjkPersonService {
    @Autowired
    WhjkPackageRelService packageRelService;
    @Autowired
    WhjkPackageRelInfoService packageRelInfoService;
    @Autowired
    WhjkTeamCheckInfoService teamCheckInfoService;
    @Autowired
    WhjkTeamGroupService teamGroupService;
    @Autowired
    WhjkZhxmService zhxmService;
    @Autowired
    NoUtils noUtils;
    @Autowired
    WhjkTeamGroupItemService teamGroupItemService;
    @Autowired
    WhjkSwitchService switchService;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public WhjkPersonDto registration(WhjkPersonDto whjkPersonDto) {
        List<ZhxmVo> itemList = new ArrayList<>();
        //登记类型(1:个人,2:团队)
        if (whjkPersonDto.getRegType().equals("1")) {
            itemList = whjkPersonDto.getChangeItemList();
            Assert.isTrue(itemList.size() > 0, "至少有一个项目才能");
        } else {
            Assert.notNull(whjkPersonDto.getTeamId(), "单位id不能为空");
            Assert.notNull(whjkPersonDto.getGroupId(), "分组id不能为空");
            //团体预约不加项目，等登记再插入
            //查询分组下的项目
            List<WhjkTeamGroupItem> list = teamGroupItemService.list(new LambdaQueryWrapper<WhjkTeamGroupItem>()
                    .eq(WhjkTeamGroupItem::getGroupId, whjkPersonDto.getGroupId())
                    .eq(WhjkTeamGroupItem::getDelFlag, 0));
            WhjkTeamGroup teamGroup = teamGroupService.getById(whjkPersonDto.getGroupId());
            itemList = list.stream().map(f -> {
                ZhxmVo zhxmVo = new ZhxmVo();
                zhxmVo.setZhxmId(f.getItemId());
                zhxmVo.setZhmc(f.getItemName());
                zhxmVo.setAddFlag(f.getAddFlag());
                zhxmVo.setSjjg(f.getSjjg());
                zhxmVo.setDz(f.getDz());
                zhxmVo.setBzjg(f.getBzjg());
                if ("1".equals(f.getAddFlag())) zhxmVo.setTcId(teamGroup.getPacId());
                return zhxmVo;
            }).collect(Collectors.toList());
        }
        whjkPersonDto.setPy(PinYinUtil.getPinyin(whjkPersonDto.getName()));
        whjkPersonDto.setRegisterTime(LocalDateTime.now());
        whjkPersonDto.setFileNo(whjkPersonDto.getIdCard());
        whjkPersonDto.setRegisterDoctor(SecurityUtils.getUser().getName());
        //体检状态(0:预约,1:登记,2:检查中(科室分检),4:分检完成3:已终检)
        if (whjkPersonDto.getPeStatus().equals("1")) {
            //登记才生成编号
            whjkPersonDto.setRegSerialNo(noUtils.generateNumTj());
            whjkPersonDto.setProcess("1");//流程（0-未开始1-已登记,2-已缴费,3-全科结果录入4-已回收指引单,5-已总检 6-报告打印 7-用户接收报告 ）
        }
        int count = this.count(new LambdaQueryWrapper<WhjkPerson>().eq(WhjkPerson::getIdCard, whjkPersonDto.getIdCard())
                .eq(WhjkPerson::getDelFlag, 0));
        whjkPersonDto.setPeTimes(count + 1);
        //保存登记信息
        this.save(whjkPersonDto);
        //增加项目
        addNewItems(itemList, whjkPersonDto);
        //计算变更后项目的价格
        AmountVo amountVo = calculationAmount(whjkPersonDto.getId(), itemList);
        whjkPersonDto.setTeamAmount(amountVo.getTeamAmount());
        whjkPersonDto.setPersonAmount(amountVo.getPersonAmount());
        //false-未缴费，true-已缴费
        if (amountVo.getPaySign()) {
            whjkPersonDto.setProcess("2");//流程（0-未开始1-已登记,2-已缴费,3-全科结果录入4-已回收指引单,5-已总检 6-报告打印 7-用户接收报告）
            whjkPersonDto.setChargeStatus("1");//收费标志(0未收，1已收)
            whjkPersonDto.setChargeTime(LocalDateTime.now());
        } else {
            whjkPersonDto.setChargeStatus("0");//收费标志(0未收，1已收)
        }
        //修改登记信息
        this.updateById(whjkPersonDto);
        return whjkPersonDto;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void reported(WhjkPersonDto whjkPersonDto) {
        WhjkPerson person = baseMapper.selectOne(new QueryWrapper<WhjkPerson>().lambda()
                .eq(WhjkPerson::getId, whjkPersonDto.getId())
                .eq(WhjkPerson::getDelFlag, "0")
                .eq(WhjkPerson::getPeStatus, "0"));
        Assert.notNull(person, "没有此人已预约信息");
        //体检状态(0:预约,1:登记,2:检查中,3:已终检)
        person.setPeStatus("1");
        person.setUserImage(whjkPersonDto.getUserImage());
        person.setPeDate(LocalDateTime.now());
        person.setRegisterTime(LocalDateTime.now());
        person.setRegisterDoctor(SecurityUtils.getUser().getName());

        List<ZhxmVo> itemList = whjkPersonDto.getChangeItemList();
        //过滤出变更项目和原项目
        delItems(itemList, person.getId());
        //新添加的项目
        List<ZhxmVo> changeItems = itemList.stream().filter(data -> StringUtils.isBlank(data.getRelId())).collect(Collectors.toList());
        if (changeItems.size() > 0) {
            //处理新加的项目
            addNewItems(changeItems, person);
        }
        //计算变更后项目的价格
        AmountVo amountVo = calculationAmount(person.getId(), itemList);
        person.setPersonAmount(amountVo.getPersonAmount());
        person.setTeamAmount(amountVo.getTeamAmount());
        //false-未缴费，true-已缴费
        Boolean paySign = amountVo.getPaySign();
        if (paySign) {
            //流程（0-未开始1-已登记,2-已缴费,3-全科结果录入4-已回收指引单,5-已总检 6-报告打印 7-用户接收报告 ）
            person.setProcess("2");
            person.setChargeStatus("1");//收费标志(0未收，1已收)
            person.setChargeTime(LocalDateTime.now());
        } else {
            person.setProcess("1");
            person.setChargeStatus("0");//收费标志(0未收，1已收)
        }
        person.setRegSerialNo(noUtils.generateNumTj());
        baseMapper.updateById(person);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void singleChangeSave(ChangeItemSaveReqDto changeItemSaveReqDto) {
        //获取
        WhjkPerson person = this.getById(changeItemSaveReqDto.getPersonId());
        Assert.notNull(person, "登记人id异常");
        Assert.isTrue(!"3".equals(person.getPeStatus()), "已经总检的用户，无法变更项目");
        Assert.isTrue("0".equals(person.getChargeStatus()), "已缴费用户，无法变更项目");
        //变更后项目明细
        List<ZhxmVo> itemList = changeItemSaveReqDto.getChangeItemList();
        //过滤出变更项目和原项目
        delItems(itemList, person.getId());

        //新添加的项目
        List<ZhxmVo> changeItems = itemList.stream().filter(data -> StringUtils.isBlank(data.getRelId())).collect(Collectors.toList());
        if (changeItems.size() > 0) {
            //处理新加的项目
            addNewItems(changeItems, person);
        }
        //计算变更后项目的价格
        AmountVo amountVo = calculationAmount(person.getId(), itemList);
        //修改套餐，金额，支付状态
        WhjkPerson updReg = new WhjkPerson();
        updReg.setTcId(StringUtils.isBlank(changeItemSaveReqDto.getTcId()) ? "" : changeItemSaveReqDto.getTcId());
        updReg.setId(changeItemSaveReqDto.getPersonId());
        updReg.setPersonAmount(amountVo.getPersonAmount());
        updReg.setTeamAmount(amountVo.getTeamAmount());
        //false-未缴费，true-已缴费
        Boolean paySign = amountVo.getPaySign();
        if (paySign) {
            //流程（0-未开始1-已登记,2-已缴费,3-全科结果录入4-已回收指引单,5-已总检 6-报告打印 7-用户接收报告 ）
            updReg.setProcess("2");
            updReg.setChargeStatus("1");//收费标志(0未收，1已收)
            updReg.setChargeTime(LocalDateTime.now());
        } else {
            person.setProcess("1");
            updReg.setChargeStatus("0");
        }
        this.updateById(updReg);

    }

    /**
     * 删除项目
     */
    private void delItems(List<ZhxmVo> itemList, String personId) {
        //原有的原项目
        List<String> primordialItem = itemList.stream().map(ZhxmVo::getRelId).filter(StringUtils::isNotBlank).collect(Collectors.toList());
        //要删除的项目
        List<WhjkPackageRel> packageRelList = packageRelService.list(new QueryWrapper<WhjkPackageRel>().lambda()
                .eq(WhjkPackageRel::getPeId, personId)
                .notIn(!CollectionUtils.isEmpty(primordialItem), WhjkPackageRel::getId, primordialItem)
                .eq(WhjkPackageRel::getDelFlag, "0"));
        packageRelList.forEach(f -> {
            Assert.isTrue(!"1".equals(f.getCheckStatus()), "项目已做,无法删除!");
            if (f.getSjjg().compareTo(BigDecimal.ZERO) != 0) {
                Assert.isTrue(!"1".equals(f.getPayStatus()), "项目已经缴费,无法删除!");
            }
            //删除非保留的原来项目
            f.setDelFlag("1");
            packageRelService.updateById(f);
            //删除子项
            packageRelInfoService.update(WhjkPackageRelInfo.builder().delFlag("1").build(), new LambdaQueryWrapper<WhjkPackageRelInfo>()
                    .eq(WhjkPackageRelInfo::getRelId, f.getId()));
        });
    }

    /**
     * 计算变更后项目的价格
     */
    private AmountVo calculationAmount(String personId, List<ZhxmVo> itemList) {
        //原有的原项目
        List<ZhxmVo> oldRelList = itemList.stream().filter(f -> StringUtils.isNotBlank(f.getRelId())).collect(Collectors.toList());
        //查询变更后的体检项目
        List<WhjkPackageRel> newRelList = packageRelService.list(new QueryWrapper<WhjkPackageRel>().lambda()
                .eq(WhjkPackageRel::getPeId, personId)
                .eq(WhjkPackageRel::getDelFlag, "0"));
        List<ZhxmVo> changeRelList = new ArrayList<>();
        //判断原有的项目是否价格发生变化
        if (oldRelList.size() > 0) {
            changeRelList = oldRelList.stream().filter(f -> {
                List<WhjkPackageRel> collect = newRelList.stream().filter(w -> w.getId().equals(f.getRelId())).collect(Collectors.toList());
                if ((collect.size() > 0) && (collect.get(0).getSjjg().compareTo(f.getSjjg()) != 0)) {
                    boolean b = collect.stream().noneMatch(q -> (q.getSjjg().compareTo(BigDecimal.ZERO) != 0) && (q.getPayStatus().equals("1") || q.getCheckStatus().equals("1")));
                    Assert.isTrue(b, "已经缴费的或者已检查的无法变更价格!!!");
                }
                return (collect.size() > 0) && (collect.get(0).getSjjg().compareTo(f.getSjjg()) != 0);
            }).collect(Collectors.toList());
        }
        AmountVo amountVo = new AmountVo();
        for (WhjkPackageRel item : newRelList) {
            if (changeRelList.size() > 0) {
                List<ZhxmVo> collect = changeRelList.stream().filter(w -> w.getRelId().equals(item.getId())).collect(Collectors.toList());
                if (collect.size() > 0) {
                    ZhxmVo zhxmVo = collect.get(0);
                    item.setBzjg(zhxmVo.getBzjg());
                    item.setDz(zhxmVo.getDz());
                    item.setSjjg(zhxmVo.getSjjg());
                    packageRelService.updateById(item);
                }
            }
            //缴费方式（0-个人支付，1-单位支付）
            if ("1".equals(item.getPayMode())) {
                amountVo.setPersonAmount(amountVo.getPersonAmount().add(item.getSjjg()));
            } else if ("2".equals(item.getPayMode())) {
                amountVo.setTeamAmount(amountVo.getTeamAmount().add(item.getSjjg()));
            } else {
                log.info("项目id: " + item.getId() + "没有设置支付方式");
                throw new RuntimeException("有项目没有设置支付方式,操作失败");
            }
            //缴费状态（0-未缴费，1-已缴费，2-已退费，3-申请退费中）
            if ("0".equals(item.getPayStatus())) {
                amountVo.setPaySign(false);
            }
        }
        return amountVo;
    }

    /**
     * 处理新加的项目
     */
    private void addNewItems(List<ZhxmVo> changeItems, WhjkPerson person) {
        List<WhjkPackageRel> relList = changeItems.stream().map(changeItem -> {
            //   String payStatus = changeItem.getSjjg().compareTo(BigDecimal.ZERO) == 0 ? "1" : "0";
            //判断是否已缴费（个检、团检）
            return WhjkPackageRel.builder()
                    .peId(person.getId())
                    .xmId(changeItem.getZhxmId())
                    .addFlag(changeItem.getAddFlag())
                    .payMode(person.getRegType())//缴费方式（1-个人支付，2-单位支付）
                    .tcId(changeItem.getTcId())
                    .payStatus("0")//缴费状态（0-未缴费，1-已缴费，2-已退费，3-申请退费中）
                    .checkStatus("0")//检查状态（0-未检查，1-已检查,2-弃检,3-未保存）
                    .sjjg(changeItem.getSjjg())
                    .bzjg(changeItem.getBzjg())
                    .dz(changeItem.getDz())
                    .build();
        }).collect(Collectors.toList());
        packageRelService.saveBatch(relList);
        //保存子项
        savePackageRelInfo(relList, person.getId());
    }

    private void savePackageRelInfo(List<WhjkPackageRel> items, String peId) {
        //报告表生成明细记录
        //将关联表转换成map，方便后面取出id
        Map<String, String> map = items.stream().collect(Collectors.toMap(WhjkPackageRel::getXmId, WhjkPackageRel::getId));
        //获取组合项目id集合
        List<String> xmIdList = items.stream().map(WhjkPackageRel::getXmId).collect(Collectors.toList());
        //获取组合项目下的所有的基础项目
        List<WhjkXm> tjxmList = baseMapper.findJcxmInfoByZhId(new QueryWrapper<>()
                .eq("t1.del_flag", 0)
                .eq("t2.del_flag", 0)
                .in("t1.zhxm_id", xmIdList));
        if (tjxmList.size() > 0) {
            List<WhjkPackageRelInfo> collect = tjxmList.stream().map(data -> {
                WhjkPackageRelInfo packageRelInfo = new WhjkPackageRelInfo();
                packageRelInfo.setRelId(map.get(data.getZhxmId()));
                packageRelInfo.setJcxmId(data.getId());
                packageRelInfo.setPeId(peId);
                packageRelInfo.setZhxmId(data.getZhxmId());
                return packageRelInfo;
            }).collect(Collectors.toList());
            packageRelInfoService.saveBatch(collect);
        }
    }

    @Override
    public Page<WhjkPersonDto> personPage(PersonDto person) {
        return baseMapper.personPage(new Page<>(person.getCurrent(), person.getSize()), new QueryWrapper<>()
                .eq("t1.del_flag", 0)
                .eq(StringUtils.isNotBlank(person.getTeamId()), "t1.team_id", person.getTeamId())
                .eq(StringUtils.isNotBlank(person.getGroupId()), "t1.group_id", person.getGroupId())
                .eq(StringUtils.isNotBlank(person.getProcess()), "t1.process", person.getProcess())
                .eq(StringUtils.isNotBlank(person.getRegType()), "t1.reg_type", person.getRegType())
                .eq(StringUtils.isNotBlank(person.getPeStatus()), "t1.pe_status", person.getPeStatus())
                .like(StringUtils.isNotBlank(person.getRegSerialNo()), "t1.reg_serial_no", person.getRegSerialNo())
                .like(StringUtils.isNotBlank(person.getIdCard()), "t1.id_card", person.getIdCard())
                .like(StringUtils.isNotBlank(person.getName()), "t1.name", person.getName())
                .orderByDesc("t1.create_time")
                .apply(StringUtils.isNotBlank(person.getPeDate()), "date_format(t1.pe_date,'%Y-%m-%d')='" + person.getPeDate() + "'")
        );
    }

    /**
     * 根据用户id查询对应用户信息以及该用户的体检项目
     *
     * @param id
     * @return
     */
    @Override
    public WhjkPersonZhxmDto getTree(String id) {
        WhjkPersonZhxmDto pzDto = new WhjkPersonZhxmDto();
        //查询用户
        pzDto.setPerson(this.getById(id));
        List<WhjkRelZhxmDto> personZhxms = this.baseMapper.getPersonZhxms(id);
        //检查类型-医生检查
        List<WhjkRelZhxmDto> ysjcList = personZhxms.stream()
                .filter(i -> i.getJclx().equals("1"))
                .collect(Collectors.toList());
        //检查类型-检验项目
        List<WhjkRelZhxmDto> jyxmList = personZhxms.stream()
                .filter(i -> i.getJclx().equals("2"))
                .collect(Collectors.toList());
        //检查类型-功能检查
        List<WhjkRelZhxmDto> gnjcList = personZhxms.stream()
                .filter(i -> i.getJclx().equals("3"))
                .collect(Collectors.toList());
        pzDto.setYsjcZhxmList(ysjcList);
        pzDto.setJyxmZhxmList(jyxmList);
        pzDto.setGnjcZhxmList(gnjcList);
        return pzDto;
    }

    /**
     * 今日待检
     *
     * @param whjkTodayTjDto
     * @return
     */
    @Override
    public Page<WhjkPerson> TodayTjPage(WhjkTodayTjDto whjkTodayTjDto) {
        return this.baseMapper.todayTjPerson(new Page<>(whjkTodayTjDto.getCurrent(), whjkTodayTjDto.getSize()), whjkTodayTjDto);
    }

    @Override
    public WhjkPersonDto getByPersonId(String id) {
        WhjkPersonDto personDto = this.baseMapper.getByIdVo(new QueryWrapper<>().eq("t1.id", id));
        List<WhjkPackageRelPo> list = packageRelService.selectByCheckStatus(new QueryWrapper<>()
                .eq("t1.del_flag", 0)
                .eq("t1.pe_id", id)
                .orderByAsc("t2.jclx"));
        List<ZhxmVo> zhxmVoList = list.stream().map(f -> {
            ZhxmVo zhxmVo = new ZhxmVo();
            zhxmVo.setRelId(f.getId());
            zhxmVo.setZhxmId(f.getXmId());
            zhxmVo.setZhmc(f.getZhmc());
            zhxmVo.setAddFlag(f.getAddFlag());
            zhxmVo.setSjjg(f.getSjjg());
            zhxmVo.setDz(f.getDz());
            zhxmVo.setBzjg(f.getBzjg());
            zhxmVo.setTcId(f.getTcId());
            zhxmVo.setZhbh(f.getZhbh());
            zhxmVo.setPayStatus(f.getPayStatus());
            zhxmVo.setCheckStatus(f.getCheckStatus());
            zhxmVo.setTcmc(f.getTcmc());
            zhxmVo.setJclx(f.getJclx());
            return zhxmVo;
        }).collect(Collectors.toList());
        personDto.setChangeItemList(zhxmVoList);
        int count = this.count(new LambdaQueryWrapper<WhjkPerson>()
                .eq(WhjkPerson::getPId, id)
                .eq(WhjkPerson::getDelFlag, 0));
        personDto.setType(count != 0);
        return personDto;
    }

    @Override
    public void personExcel(HttpServletResponse response, PersonDto person) throws Exception {
        person.setSize(-1);
        List<WhjkPersonDto> records = this.personPage(person).getRecords();
        List<WhjkPersonExcel> userList = records.stream()
                .limit(10000)
                .map(whjkPerson -> {
                    WhjkPersonExcel whjkPersonExcel = new WhjkPersonExcel();
                    BeanUtils.copyProperties(whjkPerson, whjkPersonExcel);
                    return whjkPersonExcel;
                })
                .collect(Collectors.toList());


        //导出-下载
        ExcelImportUtils<WhjkPersonExcel> excelImportUtils = new ExcelImportUtils<>(WhjkPersonExcel.class);
        //设置表头
        //excelImportUtils.SelectedHeaders(person.getHeadList());
        //如下面两个方法颠倒位置，则下拉无效，先设置下拉，再下载。
        //excelImportUtils.setExcelDropdownValue("fieldNames", attrValues); //设置对应字段的下拉列表的值
        excelImportUtils.downLoad(response, userList, "列表信息", "体检详情");  //下载
    }

    @Override
    public void review(WhjkPersonDto whjkPersonDto) {
        int count = this.count(new LambdaQueryWrapper<WhjkPerson>()
                .eq(WhjkPerson::getPId, whjkPersonDto.getId()));
        Assert.isTrue(count == 0, "已有复检信息请勿重复添加!!!");
        WhjkPerson oldPerson = this.getById(whjkPersonDto.getId());
        List<String> zhxmIds = whjkPersonDto.getZhxmIds();
        Assert.isTrue(zhxmIds.size() > 0, "复检至少有一个项目才能");
        //查询要复检的项目
        List<WhjkZhxm> zhxmList = zhxmService.list(new LambdaQueryWrapper<WhjkZhxm>()
                .in(WhjkZhxm::getId, zhxmIds));
        final BigDecimal[] price = {BigDecimal.ZERO};
        List<ZhxmVo> itemList = zhxmList.stream().map(f -> {
            ZhxmVo zhxmVo = new ZhxmVo();
            zhxmVo.setZhxmId(f.getId());
            zhxmVo.setZhmc(f.getZhmc());
            zhxmVo.setAddFlag("2");
            zhxmVo.setSjjg(f.getSjjg());
            zhxmVo.setDz(f.getDz());
            zhxmVo.setBzjg(f.getBzjg());
            zhxmVo.setTcId("");
            price[0] = price[0].add(f.getSjjg());
            return zhxmVo;
        }).collect(Collectors.toList());
        WhjkPerson newPerson = WhjkPerson.builder()
                .name(oldPerson.getName())
                .py(oldPerson.getPy())
                .userImage(oldPerson.getUserImage())
                .idCard(oldPerson.getIdCard())
                .regSerialNo(noUtils.generateNumTj())//生成编号
                .fileNo(oldPerson.getFileNo())
                .peStatus("1")//体检状态(0:预约,1:登记,2:检查中(科室分检),4:分检完成3:已终检)
                .process("1")//流程（0-未开始1-已登记,2-已缴费,3-全科结果录入4-已回收指引单,5-已总检 6-报告打印 7-用户接收报告 ）
                .chargeStatus("0")//收费标志(0未收，1已收)
                .peTimes(oldPerson.getPeTimes() + 1)
                .birthday(oldPerson.getBirthday())
                .gender(oldPerson.getGender())
                .nation(oldPerson.getNation())
                .bizTypeId(oldPerson.getBizTypeId())
                .peTypeId(oldPerson.getPeTypeId())
                .address(oldPerson.getAddress())
                .email(oldPerson.getEmail())
                .regType(oldPerson.getRegType())
                .teamId(oldPerson.getTeamId())
                .groupId(oldPerson.getGroupId())
                .source(oldPerson.getSource())
                .pId(oldPerson.getId())
                .build();
        //登记类型(1:个人,2:团队)
        if (oldPerson.getRegType().equals("1")) {
            newPerson.setPersonAmount(price[0]);
        } else {
            newPerson.setTeamAmount(price[0]);
        }
        //保存登记信息
        this.save(newPerson);
        //增加项目
        addNewItems(itemList, newPerson);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void importExcelByTemplate(importExcelDto importDTO) throws Exception {
        Assert.notNull(importDTO.getTeamId(), "单位id不能为空");
        Assert.notNull(importDTO.getGroupId(), "分组id不能为空");
        WhjkTeamCheckInfo checkInfo = teamCheckInfoService.getById(importDTO.getTeamId());
        Assert.isTrue(checkInfo != null, "单位id异常");
        WhjkTeamGroup teamGroup = teamGroupService.getById(importDTO.getGroupId());
        Assert.isTrue(teamGroup != null, "分组id异常");
        MultipartFile file = importDTO.getFile();
        //读取 - 按ExcelProperty注解的名字读取，excel文件的单元格标题名字不是ExcelProperty注解的名字时，则无法读取此单元格
        ExcelImportUtils<InquiryTemplateVo> excelImportUtils = new ExcelImportUtils<>(InquiryTemplateVo.class);
        List<InquiryTemplateVo> templates = excelImportUtils.excelImport(file.getInputStream());//返回读取到的数据列表
        if (templates.size() > 0) {
            for (int i = 0; i < templates.size(); i++) {
                InquiryTemplateVo vo = templates.get(i);
                WhjkPersonDto personDto = new WhjkPersonDto();
                personDto.setName(vo.getName());
                boolean validCard = IdcardUtil.isValidCard(vo.getIdCard());
                Assert.isTrue(validCard, "第" + i + 2 + "排," + vo.getName() + "身份证不合法");
                //如果是合法身份证号 就直接从身份证号里面获取年龄，生日,性别
                Integer age = IdcardUtil.getAgeByIdCard(vo.getIdCard());
                personDto.setAge(age);
                //1男 0女
                Integer gender = IdcardUtil.getGenderByIdCard(vo.getIdCard());
                personDto.setGender(String.valueOf(gender));
                personDto.setIdCard(vo.getIdCard());
                personDto.setPhone(vo.getPhone());
                personDto.setMarriage(gatMarriage(vo.getMarriage()));
                personDto.setAddress(vo.getAddress());
                personDto.setTeamId(importDTO.getTeamId());
                personDto.setGroupId(importDTO.getGroupId());
                personDto.setPeTypeId(importDTO.getPeTypeId());
                personDto.setRegType("2");
                personDto.setPeStatus("0");
                this.registration(personDto);
            }
        }
    }

    private String gatMarriage(String mar) {
        String marriage = "4";
        if (StringUtils.isNotBlank(mar)) {
            if (mar.equals("未婚")) {
                marriage = "0";
            } else if (mar.equals("已婚")) {
                marriage = "1";
            } else if (mar.equals("离异")) {
                marriage = "2";
            } else if (mar.equals("丧偶")) {
                marriage = "3";
            } else if (mar.equals("其他")) {
                marriage = "4";
            }
        }
        return marriage;
    }

    /**
     * 流程（
     * 0-未开始
     * 1-已登记,
     * 2-已缴费,
     * 3-全科结果录入完成
     * 4-已回收指引单,
     * 4.1-初审 4.2-总审 4.3-终审核
     * 5-已总检
     * 6-报告打印
     * 7-用户接收报告）
     *
     * @param conclusionAdviceDto
     */
    @Override
    public void saveAdvice(ConclusionAdviceDto conclusionAdviceDto) {
        WhjkPerson person = this.getById(conclusionAdviceDto.getPeId());
        if (person.getProcess().equals("0") || person.getProcess().equals("1") || person.getProcess().equals("2") || person.getProcess().equals("3")) {
            throw new RuntimeException("还没到该节点无法保存总检");
        }
        if (person.getProcess().equals("5") || person.getProcess().equals("6") || person.getProcess().equals("7")) {
            throw new RuntimeException("已经保存总检,请不要重复操作");
        }
        if (person.getProcess().equals("4") || person.getProcess().equals("4.1") || person.getProcess().equals("4.2")) {
            person.setPeConclusion(conclusionAdviceDto.getPeConclusion());
            person.setPeAdvice(conclusionAdviceDto.getPeAdvice());
            person.setProcess("5");
            person.setPeStatus("3");
            person.setInsMark("1");
            person.setInsDoctor(SecurityUtils.getUser().getName());
            person.setInsDate(LocalDateTime.now());
            this.updateById(person);
        }
    }

    @Override
    public void backAdvice(String peId) {
        WhjkPerson person = this.getById(peId);
        if (!(person.getProcess().equals("5") || person.getProcess().equals("6") || person.getProcess().equals("7"))) {
            throw new RuntimeException("没有保存总检,无法撤回");
        }
        //判断流程上级id
        List<WhjkSwitch> switchList = switchService.list(new LambdaQueryWrapper<WhjkSwitch>()
                .eq(WhjkSwitch::getType, "audit")
                .eq(WhjkSwitch::getOpen, 1));
        if (!switchList.isEmpty()) {
            // 使用 Stream 排序
            switchList = switchList.stream().sorted(Comparator.comparing(WhjkSwitch::getIdentification))
                    .collect(Collectors.toList());
            WhjkSwitch whjkSwitch = switchList.get(0);
            person.setProcess(whjkSwitch.getIdentification());
        }else {
            person.setProcess("4");
        }
        person.setPeStatus("2");
        person.setInsMark("0");
        person.setInsDoctor(null);
        person.setInsDate(null);
        this.updateById(person);
    }

    @Override
    public Page<WhjkPerson> PersonFilePage(WhjkTjdaDto whjkTjdaDto) {
        // 构建查询条件
        QueryWrapper<WhjkPerson> queryWrapper = new QueryWrapper<WhjkPerson>()
                .eq("del_flag", 0)
                .eq("ins_mark", 1)
                .like(StringUtils.isNotBlank(whjkTjdaDto.getName()), "name", whjkTjdaDto.getName())
                .like(StringUtils.isNotBlank(whjkTjdaDto.getIdCard()), "id_card", whjkTjdaDto.getIdCard());

        // 获取原始数据列表
        IPage<WhjkPerson> pageData = this.page(new Page<>(whjkTjdaDto.getCurrent(), whjkTjdaDto.getSize()), queryWrapper);
        List<WhjkPerson> dataList = pageData.getRecords();

        // 获取每个id_card对应的最新记录
        Map<String, WhjkPerson> filteredMap = dataList.stream()
                .collect(Collectors.toMap(
                        WhjkPerson::getIdCard,
                        Function.identity(),
                        (p1, p2) -> p1.getPeDate().compareTo(p2.getPeDate()) > 0 ? p1 : p2
                ));

        // 获取分页结果
        List<WhjkPerson> pageResult = new ArrayList<>(filteredMap.values());
        Page<WhjkPerson> page = new Page<>(whjkTjdaDto.getCurrent(), whjkTjdaDto.getSize());
        page.setRecords(pageResult);
        page.setTotal(pageData.getTotal()); // 设置总条数
        return page;
    }
}
